#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cassert>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "task.hpp"

using namespace std;

#define Child_Process_Size 5

int command_wait(int fd, bool &flag)
{
    uint32_t command = 0;
    ssize_t sz = read(fd, &command, sizeof(command));
    // cout << "command:" << command << endl;
    // cout << "sz:" << sz << endl;
    if (sz == 0)
        flag = true;
    else
        assert(sz == sizeof(command));
    return command;
}

void command_push(pid_t child_process, int fd, int command)
{
    cout << "main:child_process" << child_process << "\tfd" << fd << "\tcommand" << command << endl;
    ssize_t ret = write(fd, &command, sizeof(command));
    // cout << ret << "!" << endl;
}

int main()
{
    load();
    vector<pair<pid_t, int>> slots;
    for (int i = 0; i < Child_Process_Size; ++i)
    {
        // 建立管道
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        assert(n == 0);
        (void)n;
        pid_t id = fork();
        assert(id != -1);

        if (id == 0)
        {
            // child
            // 关闭信道
            close(pipefd[1]);
            while (true)
            {
                bool flag = false;
                int command = command_wait(pipefd[0], flag);
                // cout << command << "#" << endl;
                // printf("%p888888\n", callbacks[command]);
                if (flag)
                    break;
                if (command >= 0 && command < callbacks.size())
                {
                    callbacks[command]();
                }
                else
                {
                    cout << "非法command:" << command << endl;
                }
            }
            exit(1);
            // 执行command
        }
        // father
        close(pipefd[0]);
        slots.push_back(pair<pid_t, int>(id, pipefd[1]));
    }

    // 派发任务
    srand((unsigned int)time(nullptr));
    int time = 5;
    ////随机派发
    // while(time--)
    // {
    //     int command = rand() % callbacks.size();

    //     int child = rand() % Child_Process_Size;

    //     command_push(slots[child].first, slots[child].second, command);

    //     sleep(1);
    // }
    ////指定派发
    while (true)
    {
        cout << "******************************" << endl;
        cout << "** 1. describe   2. command **" << endl;
        cout << "*********  0. quit  **********" << endl;
        cout << "please cin your choice:";
        int child = rand() % Child_Process_Size;
        int command;
        bool quit = false;
        int choice = -1;
        cin >> choice;
        switch (choice)
        {
        case 1:
            describe();
            break;
        case 2:
            cout << "please cin command:";
            cin >> command;
            command_push(slots[child].first, slots[child].second, command);
            break;
        case 0:
            quit = true;
            break;
        default:
            cout << "please recin:";
            break;
        }
        if (quit)
            break;
    }

    for (const auto &e : slots)
    {
        close(e.second);
    }

    for (const auto &e : slots)
    {
        pid_t ret = waitpid(e.first, nullptr, 0);
        assert(ret >= 0);
    }

    return 0;
}